package com.jfsnpm.jfsnpm.plugin.signpdf;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.util.Calendar;

import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.PDSignature;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.SignatureOptions;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSigProperties;
import org.apache.pdfbox.pdmodel.interactive.digitalsignature.visible.PDVisibleSignDesigner;

import com.jfsnpm.jfsnpm.core.util.AppHelper;
import com.jfsnpm.jfsnpm.plugin.keystore.keyStoreManage;

public class signPdf extends CreateSignatureBase {
	private String signUser=null;
	private String signPassword=null;
	private String signName=null;
	private String signLocation="CN";
	private String signReason="Sign";
	private boolean signVisible = false;
	private int x=0;
	private int y=0;
	/**
	 * 显示尺寸 = 原尺寸 * (100+zoom)/100
	 */
	private float zoom=0;
	private File image=null;
	private int page = 1;
	private File file=null;
	private File fileSign=null;
	
	private SignatureOptions options;
	public signPdf(String signUser,String signPassword,
			File file) throws Throwable{
		this(signUser, signPassword, file, null);
		String fileName = file.getName();
		fileName = fileName.substring(0, fileName.length()-4)+"_sign.pdf";
		fileSign = new File(file.getParent()+"\\"+fileName);
	}
	public signPdf(String signUser,String signPassword,
			File file,File fileSign) throws Throwable{
		this(signUser, signPassword, file, fileSign, signUser, "CN", "Sign");
	}
	public signPdf(String signUser,String signPassword,
			File file,File fileSign,
			String signName,String signLocation,String signReason) throws Throwable{
		this(signUser, signPassword, file, fileSign,
				false, fileSign, 0, 0, 1, 1, signName, signLocation, signReason);
	}
	public signPdf(String signUser,String signPassword,
			File file,File fileSign,boolean signVisible,
			File image,int x,int y,float zoom,int page,
			String signName,String signLocation,String signReason) throws Throwable{
		AppHelper.assertNotEmpty(signUser);
		AppHelper.assertNotEmpty(signPassword);
		this.signUser = signUser;
		this.signPassword = signPassword;
        this.file = file;
        this.fileSign = fileSign;
        this.signVisible = signVisible;
        this.image = image;
        this.x = Double.valueOf(x*2.835).intValue();
        this.y = Double.valueOf(y*2.835).intValue();
        this.zoom = zoom;
        this.page = page;
        this.signName = signName;
        this.signLocation = signLocation;
        this.signReason = signReason;
	}
	public signPdf setVisible(boolean signVisible,
			File image,int x,int y,float zoom,int page){
		this.signVisible = signVisible;
        this.image = image;
        this.x = Double.valueOf(x*2.835).intValue();
        this.y = Double.valueOf(y*2.835).intValue();
        this.zoom = zoom;
        this.page = page;
		return this;
	}
	/**
	 * 执行签名动作
	 * @throws Throwable
	 */
    public void signature() throws Throwable
    {
    	if (file == null || !file.exists()) {
            throw new IOException("Document for signing does not exist");
        }
    	if (file.getName().toLowerCase().indexOf(".pdf") <= 0) {
    		throw new IOException("Document is not a PDF File");
    	}
        
    	//数字证书部分
    	keyStoreManage.assertExist(signUser, signPassword);
		KeyStore keystore = keyStoreManage.getStore();
		setPrivateKey((PrivateKey) keystore.getKey(signUser, signPassword.toCharArray()));
        Certificate[] certificateChain = keystore.getCertificateChain(signUser);
        setCertificate(certificateChain[0]);
        
        // creating output document and prepare the IO streams.
        FileOutputStream fos = new FileOutputStream(fileSign);
        // load document
        PDDocument doc = PDDocument.load(file);
        
        PDSignature signature = new PDSignature();
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
        signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
        signature.setName(signName);
        signature.setLocation(signLocation);
        signature.setReason(signReason);
        signature.setSignDate(Calendar.getInstance());
        
       
        
        if (signVisible){
        	//签名显示
            options = new SignatureOptions();
            PDVisibleSignDesigner visibleSignDesigner;
            PDVisibleSigProperties visibleSignatureProperties = new PDVisibleSigProperties();
            PDDocument docv = PDDocument.load(file);
            visibleSignDesigner = new PDVisibleSignDesigner(docv,
            		new FileInputStream(image),page);
            visibleSignDesigner.xAxis(x).yAxis(y).zoom(zoom).signatureFieldName("signature");
            
            visibleSignatureProperties.signerName(signName).signerLocation(signLocation)
            	.signatureReason(signReason).page(page).visualSignEnabled(true)
            	.setPdVisibleSignature(visibleSignDesigner).buildSignature();
            
            options.setVisualSignature(visibleSignatureProperties);
            options.setPage(visibleSignatureProperties.getPage() - 1);
            docv.close();
            doc.addSignature(signature, this, options);
        }
        else
        {
        	doc.addSignature(signature, this);
        }
        doc.saveIncremental(fos);
        doc.close();
        fos.close();
        IOUtils.closeQuietly(options);
    }
}
